From 678a65639526e649d54b2e5e0cadfb13ca913fcd Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Tue, 28 Aug 2018 01:52:54 +0200 Subject: [PATCH] babl-fish-reference: reintroduce single precision processing only for matching components for now --- babl/babl-fish-reference.c | 112 ++++++++++++++++++++++--- babl/base/type-half.c | 168 ++++++++++++------------------------- 2 files changed, 153 insertions(+), 127 deletions(-) diff --git a/babl/babl-fish-reference.c b/babl/babl-fish-reference.c index 2dceba0..0f6c4b4 100644 --- a/babl/babl-fish-reference.c +++ b/babl/babl-fish-reference.c @@ -400,6 +400,76 @@ static int compatible_components (const BablFormat *a, return 1; } +static void +ncomponent_convert_to_float (BablFormat *source_fmt, + char *source_buf, + char *source_float_buf, + int n) +{ + BablImage *src_img; + BablImage *dst_img; + + src_img = (BablImage *) babl_image_new ( + babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL); + dst_img = (BablImage *) babl_image_new ( + babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL); + + dst_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT); + dst_img->pitch[0] = (dst_img->type[0]->bits / 8); + dst_img->stride[0] = 0; + + src_img->data[0] = source_buf; + src_img->type[0] = source_fmt->type[0]; + src_img->pitch[0] = source_fmt->type[0]->bits / 8; + src_img->stride[0] = 0; + + dst_img->data[0] = source_float_buf; + + babl_conversion_process ( + assert_conversion_find (src_img->type[0], dst_img->type[0]), + (void*)src_img, (void*)dst_img, + n * source_fmt->components); + babl_free (src_img); + babl_free (dst_img); +} + +static void +ncomponent_convert_from_float (BablFormat *destination_fmt, + char *destination_float_buf, + char *destination_buf, + int n) +{ + BablImage *src_img; + BablImage *dst_img; + + src_img = (BablImage *) babl_image_new ( + babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL); + dst_img = (BablImage *) babl_image_new ( + babl_component_from_id (BABL_GRAY_LINEAR), NULL, 1, 0, NULL); + + src_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT); + src_img->pitch[0] = (src_img->type[0]->bits / 8); + src_img->stride[0] = 0; + + dst_img->data[0] = destination_buf; + dst_img->type[0] = (BablType *) babl_type_from_id (BABL_FLOAT); + dst_img->pitch[0] = destination_fmt->type[0]->bits/8; + dst_img->stride[0] = 0; + + dst_img->type[0] = destination_fmt->type[0]; + src_img->data[0] = destination_float_buf; + + babl_conversion_process ( + assert_conversion_find (src_img->type[0], dst_img->type[0]), + (void*)src_img, (void*)dst_img, + n * destination_fmt->components); + + dst_img->data[0] += dst_img->type[0]->bits / 8; + babl_free (src_img); + babl_free (dst_img); +} + + static void process_same_model (const Babl *babl, const char *source, @@ -426,19 +496,37 @@ process_same_model (const Babl *babl, if (compatible_components ((void*)babl->fish.source, (void*)babl->fish.destination)) { - ncomponent_convert_to_double ( - (BablFormat *) BABL (babl->fish.source), - (char *) source, - double_buf, - n - ); + const void *type_float = babl_type_from_id (BABL_FLOAT); - ncomponent_convert_from_double ( - (BablFormat *) BABL (babl->fish.destination), - double_buf, - (char *) destination, - n - ); + if ((babl->fish.source->format.type[0]->bits < 32 || + babl->fish.source->format.type[0] == type_float) && + (babl->fish.destination->format.type[0]->bits < 32 || + babl->fish.destination->format.type[0] == type_float)) + { + ncomponent_convert_to_float ( + (BablFormat *) BABL (babl->fish.source), + (char *) source, + double_buf, + n); + ncomponent_convert_from_float ( + (BablFormat *) BABL (babl->fish.destination), + double_buf, + (char *) destination, + n); + } + else + { + ncomponent_convert_to_double ( + (BablFormat *) BABL (babl->fish.source), + (char *) source, + double_buf, + n); + ncomponent_convert_from_double ( + (BablFormat *) BABL (babl->fish.destination), + double_buf, + (char *) destination, + n); + } } else { diff --git a/babl/base/type-half.c b/babl/base/type-half.c index f31cfa0..d163300 100644 --- a/babl/base/type-half.c +++ b/babl/base/type-half.c @@ -184,112 +184,69 @@ static void halfp2doubles(void *target, void *source, long numel) } -#define INT16_TYPE short -#define UINT16_TYPE unsigned short -#define INT32_TYPE long -#define UINT32_TYPE unsigned long - -// Prototypes ----------------------------------------------------------------- - -static int singles2halfp(void *target, void *source, int numel); -static int halfp2singles(void *target, void *source, int numel); - -//----------------------------------------------------------------------------- -// -// Routine: singles2halfp -// -// Input: source = Address of 32-bit floating point data to convert -// numel = Number of values at that address to convert -// -// Output: target = Address of 16-bit data to hold output (numel values) -// return value = 0 if native floating point format is IEEE -// = 1 if native floating point format is not IEEE -// -// Programmer: James Tursa -// -//----------------------------------------------------------------------------- - -static int singles2halfp(void *target, void *source, int numel) +static void +singles2halfp(uint16_t *hp, const uint32_t *xp, int numel) { - UINT16_TYPE *hp = (UINT16_TYPE *) target; // Type pun output as an unsigned 16-bit int - UINT32_TYPE *xp = (UINT32_TYPE *) source; // Type pun input as an unsigned 32-bit int - UINT16_TYPE hs, he, hm; - UINT32_TYPE x, xs, xe, xm; - int hes; - static int next; // Little Endian adjustment - static int checkieee = 1; // Flag to check for IEEE754, Endian, and word size - double one = 1.0; // Used for checking IEEE754 floating point format - UINT32_TYPE *ip; // Used for checking IEEE754 floating point format - if( checkieee ) { // 1st call, so check for IEEE754, Endian, and word size - ip = (UINT32_TYPE *) &one; - if( *ip ) { // If Big Endian, then no adjustment - next = 0; - } else { // If Little Endian, then adjustment will be necessary - next = 1; - ip++; - } - if( *ip != 0x3FF00000u ) { // Check for exact IEEE 754 bit pattern of 1.0 - return 1; // Floating point bit pattern is not IEEE 754 - if (next) - return 1; // not used, but silences gcc - } - if( sizeof(INT16_TYPE) != 2 || sizeof(INT32_TYPE) != 4 ) { - return 1; // short is not 16-bits, or long is not 32-bits. - } - checkieee = 0; // Everything checks out OK - } + uint16_t hs, he, hm; + uint32_t x, xs, xe, xm; + int hes; - if( source == NULL || target == NULL ) { // Nothing to convert (e.g., imag part of pure real) - return 0; + + + if( hp== NULL || xp== NULL ) { // Nothing to convert (e.g., imag part of pure real) + return; } while( numel-- ) { x = *xp++; if( (x & 0x7FFFFFFFu) == 0 ) { // Signed zero - *hp++ = (UINT16_TYPE) (x >> 16); // Return the signed zero + *hp++ = (uint16_t) (x >> 16); // Return the signed zero } else { // Not zero xs = x & 0x80000000u; // Pick off sign bit xe = x & 0x7F800000u; // Pick off exponent bits xm = x & 0x007FFFFFu; // Pick off mantissa bits if( xe == 0 ) { // Denormal will underflow, return a signed zero - *hp++ = (UINT16_TYPE) (xs >> 16); + *hp++ = (uint16_t) (xs >> 16); } else if( xe == 0x7F800000u ) { // Inf or NaN (all the exponent bits are set) if( xm == 0 ) { // If mantissa is zero ... - *hp++ = (UINT16_TYPE) ((xs >> 16) | 0x7C00u); // Signed Inf + *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf } else { - *hp++ = (UINT16_TYPE) 0xFE00u; // NaN, only 1st mantissa bit set + *hp++ = (uint16_t) 0xFE00u; // NaN, only 1st mantissa bit set } } else { // Normalized number - hs = (UINT16_TYPE) (xs >> 16); // Sign bit + hs = (uint16_t) (xs >> 16); // Sign bit hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp if( hes >= 0x1F ) { // Overflow - *hp++ = (UINT16_TYPE) ((xs >> 16) | 0x7C00u); // Signed Inf + *hp++ = (uint16_t) ((xs >> 16) | 0x7C00u); // Signed Inf } else if( hes <= 0 ) { // Underflow if( (14 - hes) > 24 ) { // Mantissa shifted all the way off & no rounding possibility - hm = (UINT16_TYPE) 0u; // Set mantissa to zero + hm = (uint16_t) 0u; // Set mantissa to zero } else { xm |= 0x00800000u; // Add the hidden leading bit - hm = (UINT16_TYPE) (xm >> (14 - hes)); // Mantissa + hm = (uint16_t) (xm >> (14 - hes)); // Mantissa if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding - hm += (UINT16_TYPE) 1u; // Round, might overflow into exp bit, but this is OK + hm += (uint16_t) 1u; // Round, might overflow into exp bit, but this is OK } *hp++ = (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero } else { - he = (UINT16_TYPE) (hes << 10); // Exponent - hm = (UINT16_TYPE) (xm >> 13); // Mantissa + he = (uint16_t) (hes << 10); // Exponent + hm = (uint16_t) (xm >> 13); // Mantissa if( xm & 0x00001000u ) // Check for rounding - *hp++ = (hs | he | hm) + (UINT16_TYPE) 1u; // Round, might overflow to inf, this is OK + *hp++ = (hs | he | hm) + (uint16_t) 1u; // Round, might overflow to inf, this is OK else *hp++ = (hs | he | hm); // No rounding } } } } - return 0; + return; } + + + //----------------------------------------------------------------------------- // // Routine: halfp2singles @@ -298,52 +255,30 @@ static int singles2halfp(void *target, void *source, int numel) // numel = Number of values at that address to convert // // Output: target = Address of 32-bit floating point data to hold output (numel values) -// return value = 0 if native floating point format is IEEE -// = 1 if native floating point format is not IEEE +// // // Programmer: James Tursa // //----------------------------------------------------------------------------- -static int halfp2singles(void *target, void *source, int numel) +static void +halfp2singles(uint32_t *xp, const uint16_t *hp, int numel) { - UINT16_TYPE *hp = (UINT16_TYPE *) source; // Type pun input as an unsigned 16-bit int - UINT32_TYPE *xp = (UINT32_TYPE *) target; // Type pun output as an unsigned 32-bit int - UINT16_TYPE h, hs, he, hm; - UINT32_TYPE xs, xe, xm; - INT32_TYPE xes; - int e; - static int next; // Little Endian adjustment - static int checkieee = 1; // Flag to check for IEEE754, Endian, and word size - double one = 1.0; // Used for checking IEEE754 floating point format - UINT32_TYPE *ip; // Used for checking IEEE754 floating point format - if( checkieee ) { // 1st call, so check for IEEE754, Endian, and word size - ip = (UINT32_TYPE *) &one; - if( *ip ) { // If Big Endian, then no adjustment - next = 0; - } else { // If Little Endian, then adjustment will be necessary - next = 1; - ip++; - } - if( *ip != 0x3FF00000u ) { // Check for exact IEEE 754 bit pattern of 1.0 - return 1; // Floating point bit pattern is not IEEE 754 - if (next) - return 1; // not used but silences gcc - } - if( sizeof(INT16_TYPE) != 2 || sizeof(INT32_TYPE) != 4 ) { - return 1; // short is not 16-bits, or long is not 32-bits. - } - checkieee = 0; // Everything checks out OK - } + uint16_t h, hs, he, hm; + uint32_t xs, xe, xm; + int32_t xes; + int e; + + - if( source == NULL || target == NULL ) // Nothing to convert (e.g., imag part of pure real) - return 0; + if( xp == NULL || hp == NULL ) // Nothing to convert (e.g., imag part of pure real) + return; while( numel-- ) { h = *hp++; if( (h & 0x7FFFu) == 0 ) { // Signed zero - *xp++ = ((UINT32_TYPE) h) << 16; // Return the signed zero + *xp++ = ((uint32_t) h) << 16; // Return the signed zero } else { // Not zero hs = h & 0x8000u; // Pick off sign bit he = h & 0x7C00u; // Pick off exponent bits @@ -354,30 +289,33 @@ static int halfp2singles(void *target, void *source, int numel) e++; hm <<= 1; } while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit - xs = ((UINT32_TYPE) hs) << 16; // Sign bit - xes = ((INT32_TYPE) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single - xe = (UINT32_TYPE) (xes << 23); // Exponent - xm = ((UINT32_TYPE) (hm & 0x03FFu)) << 13; // Mantissa + xs = ((uint32_t) hs) << 16; // Sign bit + xes = ((int32_t) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single + xe = (uint32_t) (xes << 23); // Exponent + xm = ((uint32_t) (hm & 0x03FFu)) << 13; // Mantissa *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits } else if( he == 0x7C00u ) { // Inf or NaN (all the exponent bits are set) if( hm == 0 ) { // If mantissa is zero ... - *xp++ = (((UINT32_TYPE) hs) << 16) | ((UINT32_TYPE) 0x7F800000u); // Signed Inf + *xp++ = (((uint32_t) hs) << 16) | ((uint32_t) 0x7F800000u); // Signed Inf } else { - *xp++ = (UINT32_TYPE) 0xFFC00000u; // NaN, only 1st mantissa bit set + *xp++ = (uint32_t) 0xFFC00000u; // NaN, only 1st mantissa bit set } } else { // Normalized number - xs = ((UINT32_TYPE) hs) << 16; // Sign bit - xes = ((INT32_TYPE) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single - xe = (UINT32_TYPE) (xes << 23); // Exponent - xm = ((UINT32_TYPE) hm) << 13; // Mantissa + xs = ((uint32_t) hs) << 16; // Sign bit + xes = ((int32_t) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single + xe = (uint32_t) (xes << 23); // Exponent + xm = ((uint32_t) hm) << 13; // Mantissa *xp++ = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits } } } - return 0; + return; } + + + static void convert_double_half (BablConversion *conversion, char *src, @@ -421,7 +359,7 @@ convert_float_half (BablConversion *conversion, { while (n--) { - singles2halfp (dst, src, 1); + singles2halfp ((void*)dst, (void*)src, 1); dst += dst_pitch; src += src_pitch; } @@ -437,7 +375,7 @@ convert_half_float (BablConversion *conversion, { while (n--) { - halfp2singles (dst, src, 1); + halfp2singles ((void*)dst, (void*)src, 1); dst += dst_pitch; src += src_pitch; } -- 2.30.2